package com.dib.neo.bkfs.h2;

import com.dib.neo.bkfs.fs.BKFile;
import com.dib.neo.bkfs.fs.BKPath;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.OpenOption;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Set;
import org.h2.store.fs.FilePath;

public class BKFSFilePath extends FilePath {
  private final BKPath path;

  public BKFSFilePath() {
    this(null);
  }

  public BKFSFilePath(BKPath path) {
    this.path = path;
    if(path!=null) {
      this.name = path.toString();
    }
  }

  @Override
  public long size() {
    return path.getFileInfo().getAttributes().size();
  }

  @Override
  public void moveTo(FilePath filePath, boolean b) {
    try {
      path.getFileSystem().provider().move(path, path.resolve(filePath.getName()));
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public boolean createFile() {
    try {
      return path.createNewFile();
    } catch (FileAlreadyExistsException e) {
      return true;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return false;
  }

  @Override
  public boolean exists() {
    return path.exists();
  }

  @Override
  public void delete() {

    try {
      path.getFileSystem().provider().delete(path);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public List<FilePath> newDirectoryStream() {
    List<FilePath> paths = Lists.newArrayList();
    List<BKPath> files = path.listPaths();
    for (BKPath file :files){
      paths.add(new BKFSFilePath(file));
    }
    return paths;
  }

  @Override
  public FilePath toRealPath() {
    return this;
  }

  @Override
  public FilePath getParent() {
    return new BKFSFilePath(path.getParent());
  }

  @Override
  public boolean isDirectory() {
    return path.getFileInfo().getAttributes().isDirectory();
  }

  @Override
  public boolean isAbsolute() {
    return path.isAbsolute();
  }

  @Override
  public long lastModified() {
    return path.getFileInfo().getAttributes().lastModifiedTime().toMillis();
  }

  @Override
  public boolean canWrite() {
    return true;
  }

  @Override
  public void createDirectory() {
    try {
      path.getFileSystem().provider().createDirectory(path);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public OutputStream newOutputStream(boolean append) throws IOException {
    return path.newOutputStream(append);
  }

  @Override
  public FileChannel open(String mode) throws IOException {
    Set<OpenOption> options = Sets.newHashSet();
    if(mode.contains("r"))options.add(StandardOpenOption.READ);
    if(mode.contains("w"))options.add(StandardOpenOption.WRITE);
    if(mode.contains("s"))options.add(StandardOpenOption.SYNC);
    return path.open(options);
  }

  @Override
  public InputStream newInputStream() throws IOException {
    return path.newInputStream();
  }

  @Override
  public boolean setReadOnly() {
    return false;
  }

  @Override
  public String getScheme() {
    return "bkfs";
  }

  @Override
  public FilePath getPath(String s) {
    try {
      URI uri = new URI(s);
      return new BKFSFilePath(((BKPath) Paths.get(uri)));
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}
